import os
import pandas as pd
from prettytable import PrettyTable
from gofishing.base import Uninstantiable
from gofishing.commodity import CommodityBacktest
from gofishing.broker import Broker
from gofishing.strategy import Strategy
from gofishing.observer import ObserverBase


class Analyzer(Uninstantiable):

    recordWriteDir = './record/'

    def accountBrief() -> str:
        accountValues = Broker.getAccountValues()
        accountBrief = PrettyTable()
        accountBrief.field_names = ['item', 'value']
        accountBrief.align['item'] = 'l'
        accountBrief.align['value'] = 'r'
        accountBrief.float_format['value'] = '.2'
        accountBrief.add_rows([
            ['staticValue', accountValues.staticValue],
            ['frozenMargin', accountValues.frozenMargin],
            ['frozenCommission', accountValues.frozenCommission],
            ['floatingProfit', accountValues.floatingProfit],
            ['value', accountValues.value],
            ['margin', accountValues.margin],
            ['available', accountValues.available]])
        return accountBrief.get_string()

    def holdingBrief() -> str:
        holding = Broker.getHolding()
        holdingBrief = PrettyTable()
        holdingBrief.field_names = \
            ['contractCode', 'long', 'short',
             'longOpenPrice', 'shortOpenPrice']
        holdingBrief.float_format['longOpenPrice'] = '.2'
        holdingBrief.float_format['shortOpenPrice'] = '.2'
        for contractCode in holding:
            holdingInfo = holding[contractCode]
            holdingBrief.add_row([
                contractCode, holdingInfo['long'], holdingInfo['short'],
                holdingInfo['longOpenPrice'], holdingInfo['shortOpenPrice']])
        return holdingBrief.get_string()

    def printBrokerBrief() -> str:
        print('\nholdingBrief: ')
        print(Analyzer.holdingBrief())
        print('\naccountBrief: ')
        print(Analyzer.accountBrief())
        print('\n')

    def writeRecord(prefix: str = '', writeDir: str = '') -> None:
        if not writeDir:
            writeDir = Analyzer.recordWriteDir
        if not os.path.exists(writeDir):
            os.makedirs(writeDir)

        observers = ObserverBase.observers
        observer: ObserverBase = None
        for observerID in observers:
            observer = observers[observerID]
            filePath = writeDir + prefix + '_' + observerID + '.csv'
            observer.composeRecord().to_csv(filePath)

        strategies = Strategy.strategies
        strategy: Strategy = None
        for stratID in strategies:
            strategy = strategies[stratID]
            filePath = writeDir + prefix + '_' + stratID + '.csv'
            strategy.composeRecord().to_csv(filePath)

    def plotCommodity(commodityID: str, start: pd.Timestamp, end: pd.Timestamp,
                      highFrequency=False) -> None:
        from gofishing.plot import plotKLine
        commodity: CommodityBacktest = \
            CommodityBacktest.commodities[commodityID]
        pv = commodity.continuousPV(
            start=start, end=end, highFrequency=highFrequency)
        plotKLine(pv=pv)

    def plotStrategyTrade(stratID: str,
                          start: pd.Timestamp, end: pd.Timestamp) -> None:
        from gofishing.plot import plotTrade
        strategy = Strategy.strategies[stratID]
        commodity: CommodityBacktest = strategy.commodity
        pv = commodity.continuousPV(start=start, end=end)
        tradeRecord = strategy.composeRecord()
        plotTrade(pv=pv, tradeRecord=tradeRecord)
